package com.javafactroy.kunlong.framework.elasticsearch;
import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.extern.java.Log;
import org.apache.http.HttpHost;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Log
public class EsTest {
    @Data
    public static class MyDto{

    }
    public static void main(String[] args) throws Exception {
        RestHighLevelClient resHLClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost[]{new HttpHost("192.168.1.92", 9200, "http")}));

        // 这里创建结果集
        String keyid = "id";
        String key01 = "obj1-key01";
        String key02 = "obj1-key02";

        List<Map<String, Object>> testList = new ArrayList<>();
        Map<String, Object> testObject01 = new HashMap<>();
        Map<String, Object> testObject02 = new HashMap<>();
        Map<String, Object> testObject03 = new HashMap<>();
        testObject01.put(keyid, "1");
        testObject01.put(key01, "v01");
        testObject01.put(key02, "v02");
        testObject02.put(keyid, "2");
        testObject02.put(key01, "v03");
        testObject02.put(key02, "v04");
        testObject03.put(keyid, "3");
        testObject03.put(key01, "v05");
        testObject03.put(key02, "v06");

        testList.add(testObject01);
        testList.add(testObject02);
        testList.add(testObject03);

        // 操作
        String idx = "index01";
        for(Map<String, Object> map : testList) {
            String id = String.valueOf(map.get("id"));
            IndexResponse indexResponse = addDoc(resHLClient, map, idx, id);
            System.out.println("添加后的index:" + indexResponse.toString());
            System.out.println("添加后的index状态:" + indexResponse.status());

            boolean exists = existDoc(resHLClient, idx, id);
            System.out.println("测试文档是否存在:" + exists);

            GetResponse docResponse = getDoc(resHLClient, idx, id);
            System.out.println("获取文档后返回值:" + docResponse.getSourceAsString());

           // DeleteResponse delResponse = deleteDoc(resHLClient, idx, id);
           // System.out.println("删除后:" + delResponse.toString());
           // System.out.println("删除操作的状态:" + delResponse.status());
        }

        // 批量插入
        List<Map<String, Object>> testList2 = new ArrayList<>();
        testList2.add(testObject02);

        BulkResponse bulk = batchDoc(resHLClient, testList, testList2, idx);
        System.out.println("批量操作后响应:" + bulk.toString());
        System.out.println("批量操作后的响应状态:" + bulk.status());
        // 返回false 代表没有失败
        System.out.println("批量操作后的状态:" + bulk.hasFailures());

        // 条件搜索
        SearchResponse searchResAll = queryAll(resHLClient);
        for (SearchHit hit : searchResAll.getHits().getHits()) {
            System.out.println("全量命中:" + hit.getSourceAsString());
        }

        // 包含的字段
        String[] includes = new String[]{keyid, key01};
        // 排除的字段
        String[] excludes = new String[]{key02};

        // match匹配 字段
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(key01, "v01");
        SearchResponse searchRes = query(resHLClient, idx, matchQueryBuilder, includes, excludes);

        System.out.println("条件搜索命中:" + searchRes.getHits().getHits().length);
        for (SearchHit hit : searchRes.getHits().getHits()) {
            System.out.println("命中:" + hit.getSourceAsString());
        }
        resHLClient.close();
    }

    public static IndexResponse addDoc(RestHighLevelClient restHighLevelClient, Map<String, Object> map, String idx, String id) throws IOException {
        // 指定索引库
        IndexRequest indexRequest = new IndexRequest(idx);
        // 设置参数 id 超时时间 和数据源
       // indexRequest.id(id).timeout(TimeValue.timeValueSeconds(500)).source(JSON.toJSONString(map), XContentType.JSON);
        // 执行请求
        return restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
    }

    public static boolean existDoc(RestHighLevelClient restHighLevelClient, String idx, String id) throws IOException {
        GetRequest flower = new GetRequest(idx, id);
        return restHighLevelClient.exists(flower, RequestOptions.DEFAULT);
    }

    public static GetResponse getDoc(RestHighLevelClient restHighLevelClient, String idx, String id) throws IOException {
        GetRequest flower = new GetRequest(idx, id);
        return restHighLevelClient.get(flower, RequestOptions.DEFAULT);
    }

    public static DeleteResponse deleteDoc(RestHighLevelClient restHighLevelClient, String idx, String id) throws IOException {
        DeleteRequest deleteRequest = new DeleteRequest(idx, id);
        return restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
    }

    /**
     * 测试批量 增删改查都可以 只需要更换不同的Request就可以了
     * @throws IOException
     */
    public static BulkResponse batchDoc(RestHighLevelClient restHighLevelClient,
                                        List<Map<String, Object>> updResults,
                                        List<Map<String, Object>> delResults,
                                        String idx) throws IOException {

        BulkRequest batchReq = new BulkRequest();
        for (Map<String, Object> map : updResults) {
            batchReq.add(new IndexRequest(idx)
                    .id(String.valueOf(map.get("id")))
                    .source(JSON.toJSONString(map), XContentType.JSON));
        }

        for (Map<String, Object> map : delResults) {
            batchReq.add( new DeleteRequest(idx).id( String.valueOf(map.get("id")) ) );
        }

        return restHighLevelClient.bulk(batchReq, RequestOptions.DEFAULT);
    }

    public static SearchResponse queryAll(RestHighLevelClient restHighLevelClient) throws IOException {
        SearchRequest searchReq = new SearchRequest();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        searchReq.source(searchSourceBuilder);
        return restHighLevelClient.search(searchReq, RequestOptions.DEFAULT);
    }

    public static SearchResponse query(RestHighLevelClient restHighLevelClient,
                                       String idx,
                                       MatchQueryBuilder matchQueryBuilder,
                                       String[] includes,
                                       String[] excludes) throws IOException {

        SearchRequest searchReq = new SearchRequest(idx);

        // 构造搜索条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 加入条件
        sourceBuilder.query(matchQueryBuilder);
        sourceBuilder.fetchSource(includes, excludes);
        // 分页
        sourceBuilder.from(0);
        sourceBuilder.size(2);

        //sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//
        searchReq.source(sourceBuilder);
        return restHighLevelClient.search(searchReq, RequestOptions.DEFAULT);
    }
}